package com.huawei.esdk.tpoa.authorize;

import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import org.apache.cxf.binding.soap.SoapMessage;
import org.apache.cxf.headers.Header;
import org.apache.cxf.interceptor.LoggingMessage;
import org.apache.log4j.Logger;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import com.huawei.esdk.platform.authorize.itf.AbstractAuthorizeAdapter;
import com.huawei.esdk.platform.common.MessageContext;
import com.huawei.esdk.platform.common.ThreadLocalHolder;
import com.huawei.esdk.platform.common.bean.log.InterfaceLogBean;
import com.huawei.esdk.platform.common.constants.ESDKErrorCodeConstant;
import com.huawei.esdk.platform.common.utils.ApplicationContextUtil;
import com.huawei.esdk.platform.common.utils.SHA256Utils;
import com.huawei.esdk.platform.common.utils.StringUtils;
import com.huawei.esdk.platform.log.itf.IInterfaceLog;
import com.huawei.esdk.platform.usermgr.itf.IUserManager;
import com.huawei.esdk.tp.common.constants.InfoKeys;
import com.sun.org.apache.xerces.internal.dom.ElementNSImpl;

public class SimpleAuthorize extends AbstractAuthorizeAdapter
{
    private static final Logger LOGGER = Logger.getLogger(SimpleAuthorize.class);
    
    private static final String U5ERNAME = "userName";
    
    private static final String Pa55W0rd = "password";
    
    private static final String SUCCESS = "0";
    
    private IUserManager userManager  = ApplicationContextUtil.getBean("userManager");
    
    public SimpleAuthorize(String businessName)
    {
        super(businessName);
    }
    
    @Override
    public String authorize(Object message)
    {
        if (null == message)
        {
            return Integer.toString(ESDKErrorCodeConstant.ERROR_CODE_SDK_AUTHORIZE_FAILURE);
        }
        
        SoapMessage soapMessage = (SoapMessage)message;
        
        // 获取SoapHeader中的userName和password
        String[] authorizeKeys = getAuthorizeKey(soapMessage);
        
        if (null == authorizeKeys || 2 != authorizeKeys.length)
        {
            return Integer.toString(ESDKErrorCodeConstant.ERROR_CODE_SDK_AUTHORIZE_FAILURE);
        }
        
        String userName = authorizeKeys[0];
        String pwd = authorizeKeys[1];
        
        if (null == userName || null == pwd)
        {
            return Integer.toString(ESDKErrorCodeConstant.ERROR_CODE_SDK_AUTHORIZE_FAILURE);
        }
        
        MessageContext mc = ThreadLocalHolder.get();
        if (null == mc)
        {
            mc = new MessageContext();
            ThreadLocalHolder.set(mc);
        }
        //R5C10 修改用户名传入格式，用“,"分隔开鉴权账号和预约人邮箱，例如“esdk_user,zhm01@lync.com”，前者为鉴权账号，后者为邮箱账号
        int accountSplitIndex = userName.indexOf(',');
        String checkUserName = userName;
        if(-1 != accountSplitIndex)
        {
            mc.getEntities().put(U5ERNAME, userName.substring(accountSplitIndex+1));
            checkUserName = userName.substring(0, accountSplitIndex);
        }
 //       mc.getEntities().put(Pa55W0rd, pwd);
        
        HttpServletRequest req = (HttpServletRequest)soapMessage.get("HTTP.REQUEST");
        mc.getEntities().put("remoteIp", req.getRemoteHost());
        
        mc.getEntities().put(InfoKeys.SDK_SESSION_ID.toString(), "");
        
        saveOperationLog(soapMessage);
        
        //检测eSDK用户是否存在
        //R5C10 修改用户名传入格式，用“,"分隔开鉴权账号和预约人邮箱，例如“esdk_user,zhm01@lync.com”
        
        boolean isUserExisted = userManager.checkUser(checkUserName, SHA256Utils.encrypt(pwd));
        
        if(isUserExisted)
        {
            return SUCCESS;
        }
        else
        {
            return Integer.toString(ESDKErrorCodeConstant.ERROR_CODE_SDK_AUTHORIZE_FAILURE);
        } 
    }
    
    private void saveOperationLog(SoapMessage message)
    {
        HttpServletRequest req = (HttpServletRequest)message.get("HTTP.REQUEST");
        String soapAction = req.getHeader("SOAPAction");
        
        String interfaceName = soapAction.substring(soapAction.lastIndexOf("/") + 1, soapAction.length() - 1);
        
        // TP OA 是这种格式的：esdk_tp_oa_server.scheduleConf
        if (interfaceName.contains("."))
        {
            interfaceName = interfaceName.split("\\.")[1];
        }
        
        String messageId = (String)message.getExchange().get(LoggingMessage.ID_KEY);
        if (messageId == null)
        {
            messageId = LoggingMessage.nextId();
            message.getExchange().put(LoggingMessage.ID_KEY, messageId);
        }
        
        InterfaceLogBean bean = new InterfaceLogBean();
        bean.setTransactionId(messageId);
        bean.setProduct("TP-OA");
        bean.setInterfaceType("1");
        bean.setProtocolType("SOAP");
        bean.setReq(true);
        bean.setName(interfaceName);
        bean.setSourceAddr(req.getRemoteHost());
        bean.setTargetAddr(req.getLocalAddr());
        bean.setReqTime(new Date());
        
        IInterfaceLog logger = ApplicationContextUtil.getBean("interfaceLogger");
        logger.info(bean);
    }
    
    /*
     * 获取用于校验的appid或pwd
     * key为"appid"或"pwd"
     */
    protected String[] getAuthorizeKey(SoapMessage mess)
    {
        String[] authorizeKeys = null;
        try
        {
            Header header = null;
            
            List<Header> headerList = mess.getHeaders();
            if (null != headerList && 0 < headerList.size())
            {
                header = headerList.get(0);
                
                ElementNSImpl el = (ElementNSImpl)header.getObject();
                
                if (null != el && null != el.getChildNodes())
                {
                    NodeList childList = el.getChildNodes();
                    
                    authorizeKeys = new String[2];
                    for (int i = 0; i < childList.getLength(); i++)
                    {
                        Node child = childList.item(i);
                        if (U5ERNAME.equals(child.getNodeName()))
                        {
                            authorizeKeys[0] = child.getFirstChild().getNodeValue();
                        }
                        else if (Pa55W0rd.equals(child.getNodeName()))
                        {
                            authorizeKeys[1] = child.getFirstChild().getNodeValue();
                        }
                        
                    }
                    
                }
            }
        }
        catch (Exception e)
        {
            LOGGER.error("get appid or password", e);
            authorizeKeys = null;
        }
        return authorizeKeys;
    }
    
    @Override
    public boolean needAuthorize(String funcName, Object message)
    {
        return true;
    }
    
    @Override
    public boolean reqMsgMatchesBuiness(String funcName, Object message)
    {
        if (StringUtils.isNotEmpty(funcName) && funcName.contains("esdk_tp_oa_server"))
        {
            return true;
        }
        
        return false;
    }
    
}
